/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2018 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_flexspi.h"
#include "flash_def.h"
#include "fsl_debug_console.h"
#include "fsl_cache.h"

#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_common.h"

uint16_t lutTable[20] = {0};
uint8_t dataBuffer[4096] = {0};
/* Program data buffer should be 4-bytes alignment, which can avoid busfault due to this memory region is configured as
   Device Memory by MPU. */
SDK_ALIGN(static uint8_t s_nor_program_buffer[256], 4);
SDK_ALIGN(static uint8_t s_nand_program_buffer[2112], 4);
static uint8_t s_nor_read_buffer[256];

uint8_t nor_test(void){
   status_t status;

   flexspi_flash_port_init(EXAMPLE_FLEXSPI,NOR_FLASH_PORT);

#if !(defined(XIP_EXTERNAL_FLASH))
    /* Erase whole chip . */
    PRINTF("Erasing whole chip over FlexSPI...\r\n");

    status = flexspi_nor_erase_chip(EXAMPLE_FLEXSPI);
    if (status != kStatus_Success)
    {
        return status;
    }
    PRINTF("Erase finished !\r\n");

#endif
    /* Enter quad mode. */
    status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);
    if (status != kStatus_Success)
    {
        return status;
    }

    /* Erase sectors. */
    PRINTF("Erasing Serial NOR over FlexSPI...\r\n");
    status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE);
    if (status != kStatus_Success)
    {
        PRINTF("Erase sector failure !\r\n");
        return -1;
    }

    for (uint32_t i = 0; i < 0xFFU; i++)
    {
        s_nor_program_buffer[i] = i;
    }

    status =
        flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)s_nor_program_buffer);
    if (status != kStatus_Success)
    {
        PRINTF("Page program failure !\r\n");
        return -1;
    }
    
    memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE),
           sizeof(s_nor_read_buffer));
    
    status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE);
    if (status != kStatus_Success)
    {
        PRINTF("Erase sector failure !\r\n");
        return -1;
    }
    
    memset(s_nor_program_buffer, 0xFFU, sizeof(s_nor_program_buffer));

    DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, NOR_FLASH_PAGE_SIZE);

    memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE),
           sizeof(s_nor_read_buffer));

    if (memcmp(s_nor_program_buffer, s_nor_read_buffer, sizeof(s_nor_program_buffer)))
    {
        PRINTF("Erase data -  read out data value incorrect !\r\n ");
        return -1;
    }
    else
    {
        PRINTF("Erase data - successfully. \r\n");
    }

    for (uint32_t i = 0; i < 0xFFU; i++)
    {
        s_nor_program_buffer[i] = i;
    }

    status =
        flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)s_nor_program_buffer);
    if (status != kStatus_Success)
    {
        PRINTF("Page program failure !\r\n");
        return -1;
    }

    DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, NOR_FLASH_PAGE_SIZE);

    memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE),
           sizeof(s_nor_read_buffer));

    if (memcmp(s_nor_read_buffer, s_nor_program_buffer, sizeof(s_nor_program_buffer)) != 0)
    {
        PRINTF("Program data -  read out data value incorrect !\r\n ");
        return -1;
    }
    else
    {
        PRINTF("Program data - successfully. \r\n");
    }
    return 0;
}
void nand_test(void){
    
    status_t status;
    uint8_t regStatus = 0;
    uint8_t test_flag = 0;
    flexspi_flash_port_init(EXAMPLE_FLEXSPI,NAND_FLASH_PORT);
//    PRINTF("\r\nFLEXSPI example started!\r\n");
    status = flexspi_nand_get_status(EXAMPLE_FLEXSPI, 0xC0, &regStatus);
    
    status = flexspi_nand_get_status(EXAMPLE_FLEXSPI, 0xA0, &regStatus);
    status = flexspi_nand_set_status(EXAMPLE_FLEXSPI, 0xA0, 0);
    status = flexspi_nand_get_status(EXAMPLE_FLEXSPI, 0xA0, &regStatus);
    
    status = flexspi_nand_page_data_read(EXAMPLE_FLEXSPI, (0<<6)+0, dataBuffer);   /* read in buffer */
    
    for (uint32_t i = 0; i < 2048; i++)
    {
        s_nand_program_buffer[i] = 0xb7;
    }
    
    status = flexspi_nand_flash_erase_sector(EXAMPLE_FLEXSPI, (2<<6));
    
    status = flexspi_nand_flash_page_program(EXAMPLE_FLEXSPI, (2<<6)+3, (void *)s_nand_program_buffer);
    
    status = flexspi_nand_page_data_read(EXAMPLE_FLEXSPI, (2<<6)+3, dataBuffer);   /* read in buffer */
    
    if(memcmp(s_nand_program_buffer,dataBuffer,2048) == 0)
    {
        test_flag++;
//         PRINTF(" write and read data equal\r\n ");
    }
    
    status = flexspi_nand_flash_erase_sector(EXAMPLE_FLEXSPI, (2<<6));
    
    status = flexspi_nand_page_data_read(EXAMPLE_FLEXSPI, (2<<6)+3, dataBuffer);   /* read in buffer */
    
    memset(s_nand_program_buffer,0xFF,sizeof(s_nand_program_buffer));
    
    if(memcmp(s_nand_program_buffer,dataBuffer,2048) == 0)
    {
        test_flag++;
//         PRINTF(" erase ok\r\n ");
    }
    if(test_flag == 2)
    {
        PRINTF("NAND TEST OK\r\n");
    }
}

int main(void)
{
    uint32_t i = 0;
    status_t status;
    uint32_t vendorID = 0;

    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();
    
    /* Enable D cache. */
    SCB_EnableDCache();
    
//    nor_test();
    nand_test();
//    nor_test();
//    nor_test();
//    nand_test();
    
    while (1)
    {
        
    }
}
